﻿using System.Collections.Generic;

namespace Basic
{
    /// <summary>
    /// 类实力对象缓存
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Cacher<T>
    {
        /// <summary>
        /// 缓存
        /// </summary>
        private List<T> cached;

        /// <summary>
        /// 每次增长时的数量
        /// </summary>
        private int addCount;

        /// <summary>
        /// 实例创建接口
        /// </summary>
        private System.Func<T> creator;

        /// <summary>
        /// 累计请求实例的次数
        /// </summary>
        private int allocCount;

        /// <summary>
        /// 累计归还实例使用完毕的次数
        /// </summary>
        private int useEndCount;

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="initCount">初始创建多少个实例进行缓存</param>
        /// <param name="addCount">当缓存的实例使用完毕后，再一次性创建多少实例</param>
        /// <param name="cap">存储缓存实例容器的初始容量</param>
        /// <param name="creator">创建实例</param>
        public Cacher(int initCount, int addCount, int cap, System.Func<T> creator)
        {
            this.addCount = addCount;
            this.creator = creator;
            cached = new List<T>(cap);

            for (int i = 0; i < initCount; ++i)
            {
                cached.Add(creator());
            }
        }

        /// <summary>
        /// 获取实例
        /// </summary>
        /// <returns></returns>
        public T Alloc()
        {
            ++allocCount;

            if (cached.Count == 0)
            {
                for (int i = 0; i < this.addCount; ++i)
                {
                    cached.Add(creator());
                }
            }

            T result = cached[cached.Count - 1];
            cached.RemoveAt(cached.Count - 1);

            return result;
        }

        /// <summary>
        /// 使用完毕归还
        /// </summary>
        /// <param name="t"></param>
        public void OnUseEnd(T t)
        {
            ++useEndCount;

            cached.Add(t);
        }

        /// <summary>
        /// ToString
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("T[{0}] allocCount[{1}] useEndCount[{2}] cachedCount[{3}]", typeof(T).ToString(), allocCount, useEndCount, cached.Count);
        }
    }
}
